#!/usr/bin/env python
# @Date    : 2022-05-06
# @Author  : Bright (brt2@qq.com)
# @Link    : https://gitee.com/brt2
# @Version : 0.2.0

_DESCRIPTION = """
WebServer Framework Wrapper, surport:

+ FastAPI: 自带swagger，开发效率高，适合快速开发迭代；
+ Bottle: 超轻量、稳定，适用于IOT环境；
+ Flask: 轻量、稳定、API优雅、文档完善，适用于生产环境（但需配合WSGI服务器）；
+ Tornado: 轻量、高并发、稳定，且自带服务器，适用于生产部署；
+ Sanic: 高并发，且自带swagger和服务器，适用于下一代部署环境；
"""

#####################################################################
# 便捷工具
#####################################################################

def _import_func(module, func_name):
    return getattr(module, func_name)

def interface(func):
    def wrapper(*args, **kwargs):
        try:
            func(*args, **kwargs)  # 执行当前函数体
            # print("[DEBUG]: enter {}()".format(func.__name__))
            func_call = _import_func(_frame_module, func.__name__)
            return func_call(*args, **kwargs)
        except AttributeError:
            raise NotImplementedError(f"【{func.__name__}】")
    return wrapper

#####################################################################
# Backend设置
#####################################################################

import os.path
import importlib

_MYSELF_NAME = "webframe"
_BACKEND_AVAILABLE = ["flask", "tornado", "bottle", "fastapi", "sanic"]

_frame_moudle_name = ""
_frame_module = None

def set_backend(key):
    global _frame_moudle_name, _frame_module
    key = key.lower()
    assert key in _BACKEND_AVAILABLE, f"未知的BACKEND: 【{key}】"
    new_frame_moudle_name = "frame" + key

    if _frame_moudle_name != new_frame_moudle_name:
        # 动态加载模块
        _frame_moudle_name = new_frame_moudle_name
        # 相对引用: import .frameflask (from src)
        try:
            dirname_ = "src" or os.path.basename(os.path.dirname(__file__))
            _frame_module = importlib.import_module("." + _frame_moudle_name, f"{_MYSELF_NAME}.{dirname_}")
        except ModuleNotFoundError:
            # 使用test/demo.py测试脚本时，使用内部相对引用
            _frame_module = importlib.import_module("." + _frame_moudle_name, dirname_)
    else:
        # 重载模块
        importlib.reload(_frame_module)
        # 重载子模块...??

    return _frame_module

def get_backend():
    return _frame_moudle_name[5:]

# 初始化_frame_module:
# set_backend("bottle")

def get_module(module_name):
    """ 获取web框架的子模块，如Request, Response """
    return _import_func(_frame_module, module_name)

#####################################################################
# 接口层定义（主要参考Flask实现）
#####################################################################

# 当_frame_module未初始化时，获取属性报错
# make_app=_frame_module.make_app
# redirect=_frame_module.redirect

def app_run(app, **kwargs):
    """ 执行webapp，统一各个框架的执行入口: app.run()
        host: "127.0.0.1"
        port: 8080
        debug: False
        reload: False
    """
    try:
        return _frame_module.app_run(app, **kwargs)
    except Exception as e:
        print(">>> app_run(): 程序启动异常，请查看并修复以下错误")
        print(f"[!] {e}")

def make_app(app_name, **kwargs):
    """ 创建Application
        template_folder: 指定模板文件目录
    """
    assert _frame_module is not None, "请先设置web框架，例如: webframe.set_backend('bottle')"
    return _frame_module.make_app(app_name, **kwargs)

#####################################################################
# 功能函数
#####################################################################

@interface
def redirect(*args, **kwargs):
    """ 重定向 """
@interface
def url_for(*args, **kwargs):
    """ 通过url查找并调用func """

_ALLOWED_REQUEST_TYPES = ["form", "query", "header", "cookie", "json", "bytes", "file"]
@interface
def request_data(type_):
    """ type_: form, or query, ... """
    assert type_ in _ALLOWED_REQUEST_TYPES, f"未知的request类型【{type_}】"

#####################################################################
# web
#####################################################################

@interface
def set_static_path(path_dir):
    """ 设置static目录（各框架有所不同） """
@interface
def static_file(*args, **kwargs):
    """ 获取静态文件 """
@interface
def render_template(*args, **kwargs):
    """ 渲染模板 """
@interface
def render_template_string(*args, **kwargs):
    """ 渲染模板字符串 """
